/**
 * 
 */
package com.arx.script;

import com.arx.common.GlobalConsts;
import com.arx.script.flyweight.ScriptObject;
import com.dalonedrau.pool.PooledStringBuilder;
import com.dalonedrau.pool.StringBuilderPool;

/**
 * @author Donald
 *
 */
abstract class ScriptObjectBase extends ScriptIOGroupBase {
	protected final boolean InSubStack(final ScriptObject es, final long pos) {
		boolean is = false;
		for (short i = 0; i < GlobalConsts.MAX_GOSUB; i++) {
			if (es.getSub(i) == -1) {
				es.setSub(i, pos);
				is = true;
				break;
			}
		}
		return is;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public final void ARX_SCRIPT_ComputeShortcuts(final ScriptObject es) {
		int nb = Math.min(GlobalConsts.MAX_SHORTCUT, GlobalConsts.SM_MAXCMD);
		for (int j = 1; j < nb; j++) {
			es.setShortcut(j, findScriptPos(es, super.getAsEvent(j), 0));
			if (es.getShortcut(j) >= 0) {
				String dest = "";
				GetNextWord(es, es.getShortcut(j), dest);

				if (dest.equalsIgnoreCase("{")) {
					GetNextWord(es, es.getShortcut(j), dest);

					if (dest.equalsIgnoreCase("ACCEPT")) {
						es.setShortcut(j, -1);
					}
				}
			}
		}
	}
	protected final long GetSubStack(final ScriptObject es) {
		long ret = -1;
		for (short i = 0; i < GlobalConsts.MAX_GOSUB; i++) {
			if (es.getSub(i) != -1) {
				ret = es.getSub(i);
				es.setSub(i, -1);
				break;
			}
		}
		return ret;
	}
	/**
	 * SCRIPT Precomputed Label Offsets Management
	 * @param es
	 * @param string
	 * @return
	 */
	protected final int FindLabelPos(final ScriptObject es, final String string) {
		PooledStringBuilder sb = StringBuilderPool.getInstance()
				.getStringBuilder();
		sb.append(">>");
		sb.append(string);
		int val = FindScriptPosGOTO(es, sb.toString(), 0);
		sb.returnToPool();
		return val;
	}
	/**
	 * Looks for string in script.
	 * @param es the {@link ScriptObject}
	 * @param str the {@link String} being searched for
	 * @return int
	 */
	protected final int findScriptPos(final ScriptObject es, final String str) {
		return this.findScriptPos(es, str, 0);
	}
	/**
	 * Looks for string in script.
	 * @param es the {@link ScriptObject}
	 * @param str the {@link String} being searched for
	 * @param poss the search starting position
	 * @return int
	 */
	protected final int findScriptPos(final ScriptObject es, final String str,
			final int poss) {
		int val = -1;
		if (es.hasData()) {
			int pdest = es.getData().indexOf(str, poss);
			if (pdest > -1) {
				int result = pdest + str.length();
				if (es.getData().charAt(result) <= 32) {
					val = result;
				}
			}
		}
		return val;
	}
	protected final void ClearSubStack(final ScriptObject es) {
		for (short i = 0; i < GlobalConsts.MAX_GOSUB; i++) {
			es.setSub(i, -1);
		}
	}
	public final void ARX_SCRIPT_ReleaseLabels(final ScriptObject es) {
		if (es != null && es.hasLabels()) {
			for (int i = 0; i < es.getNumberOfLabels(); i++) {
				if (es.getLabel(i).hasString()) {
					es.getLabel(i).setString(null);
				}
			}
			es.clearLabels();
		}
	}
	protected final void ReleaseScript(final ScriptObject es) {
		if (es != null) {
			if (es.hasLocalVariables()) {
				es.clearLocalVariables();
			}
			if (es.getData() != null) {
				es.setData(null);
			}
			ARX_SCRIPT_ReleaseLabels(es);
			es.clearShortcuts();
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public final void InitScript(final ScriptObject es) {
		for (short i = 0; i < GlobalConsts.MAX_GOSUB; i++) {
			es.setSub(i, -1);
		}
		es.clearAllowedEvents();
		es.clearLocalVariables();
		es.setMaster(null);
		for (short j = 0; j < GlobalConsts.MAX_SCRIPTTIMERS; j++) {
			es.setTimer(j, 0);
		}
		ARX_SCRIPT_ComputeShortcuts(es);
	}
	protected final int FindScriptPosGOTO(final ScriptObject es, final String str,
			final int poss) {
		int val = -1;
		if (es.hasData()) {
			int pdest = es.getData().indexOf(str, poss);
			if (pdest > -1) {
				int result = pdest + str.length();
				while (result < es.getData().length()) {
					if (es.getData().charAt(result) <= 32) {
						// if the character after the search word is an ASCII
						// space or other word separator,
						// return that position
						// all word separators have ASCII values of 32 or lower
						// see http://www.asciitable.com/ for more
						val = result;
						break;
					}
					pdest = es.getData().indexOf(str, result);
					result = pdest + str.length();
				}
			}
		}
		return val;
	}	
}
